﻿using System;
using System.Management;
using ClusterAware;
using ClusterAwareProperties;
using ClusterAwareWMI;

namespace ClusterAwareAdmin
{
    /// <summary>
    /// Cluster Manager Admin Class
    /// </summary>
    public class ClusterManagerAdmin : ClusterManager
    {

        #region Ctor

        /// <summary>
        /// Constructor
        /// </summary>
        public ClusterManagerAdmin()
        {
            _groupsAdminMethods = new GroupAdmin(this);
            _resourceAdminMethods = new ResourceAdmin(this);
            _resourceTypeAdminMethods = new ResourceTypeAdmin(this);
            _nodeAdminMethods = new NodeAdmin(this);
            _networkAdminMethods = new NetworkAdmin(this);
        }

        #endregion

        #region Private Properties

        private readonly GroupAdmin _groupsAdminMethods;
        private readonly ResourceAdmin _resourceAdminMethods;
        private readonly ResourceTypeAdmin _resourceTypeAdminMethods;
        private readonly NodeAdmin _nodeAdminMethods;
        private readonly NetworkAdmin _networkAdminMethods;

        #endregion

        #region Shadows Methods

        /// <summary>
        /// Connect to cluster
        /// </summary>
        new public void Connect()
        {
            base.Connect();
            if (IsConnected)
            {
                //Get ClusterPropeties
                var ch = new ClusterWmiHelpper();
                ClusterInfo = ch.GetCluster(ScopeManager);
            }
        }

        /// <summary>
        /// Disconenct from cluster and dispose objects
        /// </summary>
        new public void Disconnect()
        {
            base.Disconnect();
            if (ClusterInfo != null)
            {
                ClusterInfo.Instance.Dispose();
            }
        }

        /// <summary>
        /// Dispose objects 
        /// </summary>
        new public void Dispose()
        {
            base.Dispose();
            if (ClusterInfo != null)
            {
                ClusterInfo.Instance.Dispose();
            }
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Cluster Information Properties
        /// </summary>
        public ClusterProperties ClusterInfo { get; internal set; }

        #endregion

        #region shadows Properties

        /// <summary>
        /// Resource Group methods and properties
        /// </summary>
        new public GroupAdmin Groups
        {
            get { return _groupsAdminMethods; }
        }

        /// <summary>
        /// Resource  methods and properties
        /// </summary>
        new public ResourceAdmin Resources
        {
            get { return _resourceAdminMethods; }
        }

        /// <summary>
        /// ResourceType  methods and properties
        /// </summary>
        new public ResourceTypeAdmin ResourceTypes
        {
            get { return _resourceTypeAdminMethods; }
        }

        /// <summary>
        /// ResourceType  methods and properties
        /// </summary>
        new public NodeAdmin Nodes
        {
            get { return _nodeAdminMethods; }
        }

        /// <summary>
        /// ResourceType  methods and properties
        /// </summary>
        new public NetworkAdmin Networks
        {
            get { return _networkAdminMethods; }
        }

        #endregion

        #region public Methods


        ///<summary>
        /// Get a Cluster Properties
        ///</summary>
        ///<returns>ClusterProperties Class</returns>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Not Connected, 
        /// Failed WMI method execution
        /// </exception>
        public ClusterProperties GetCluster()
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            try
            {
                return CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.GetCluster", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.GetCluster", ex.Message), ex);

            }
        }

        ///<summary>
        /// Save a Cluster Class in Cluster
        ///</summary>
        /// <param name="clsclus">ClusterProperties class to save</param>
        ///<returns>ClusterProperties Class</returns>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Not Connected, 
        /// Failed WMI method execution
        /// </exception>
        public ClusterProperties Save(ClusterProperties clsclus)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            try
            {
                clsclus.SaveManagementObject(OperationSystem);
                var ret = new ClusterWmiHelpper().GetCluster(ScopeManager);
                if (CacheInstances)
                {
                    ClusterInfo = ret;
                }
                return ret;
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Save", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Save", ex.Message), ex);
            }
        }

        ///<summary>
        /// Determines whether the Cluster service is installed and running on a node.
        ///</summary>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Not Connected,
        /// Failed WMI method execution
        /// </exception>
        /// <returns>State of the Cluster service on the node as enumerated by the NodeClusterState enumeration.</returns>
        public NodeClusterState GetClusterState()
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            // ReSharper disable RedundantAssignment
            var ret = NodeClusterState.Unknown;
            // ReSharper restore RedundantAssignment
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);

                // ReSharper disable AssignNullToNotNullAttribute
                var outParams = clust.Instance.InvokeMethod("GetNodeClusterState", null, null);
                // ReSharper restore AssignNullToNotNullAttribute

                // ReSharper disable PossibleNullReferenceException
                ret = (NodeClusterState)Enum.Parse(typeof(NodeClusterState), outParams["ClusterState"].ToString());
                // ReSharper restore PossibleNullReferenceException
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.GetNodeClusterState", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.GetNodeClusterState", ex.Message), ex);
            }
            return ret;
        }

        ///<summary>
        /// Creates a cluster.
        ///</summary>
        ///<param name="clusterName">Cluster name.</param>
        ///<param name="nodeNames">Node names that will form the cluster.</param>
        ///<param name="ipAdresses">IP addresses that the cluster will use.</param>
        ///<param name="subnetMasks">IP address subnet masks or prefix lengths that the cluster will use.</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008,
        /// Alreadly Connected
        /// Paramenters empty or invalids,
        /// Failed WMI method execution
        /// </exception>
        public void Create(string clusterName, string[] nodeNames, string[] ipAdresses, string[] subnetMasks)
        {
            if (IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_AlreadyConnect);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "SetQuorumResource"));
            }
            if (string.IsNullOrEmpty(clusterName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "clusterName"));
            }
            try
            {
                var path = new ManagementPath("MSCluster_Cluster");
                using (var classInstance = new ManagementClass(ScopeManager, path, new ObjectGetOptions()))
                {
                    using (var inParams = classInstance.GetMethodParameters("CreateCluster"))
                    {
                        inParams["ClusterName"] = clusterName;
                        inParams["NodeNames"] = nodeNames;
                        inParams["IPAddresses"] = ipAdresses;
                        inParams["SubnetMasks"] = subnetMasks;
                        classInstance.InvokeMethod("CreateCluster", inParams, null);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Create", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Create", ex.Message), ex);
            }
        }


        ///<summary>
        /// Renames the cluster.
        ///</summary>
        ///<remarks>
        /// Rename operation will reset the cluster service
        /// </remarks>
        ///<param name="newName">New name Cluster</param>
        ///<param name="timeoutSecondsRestart">Timeout in seconds to faiured restart Service</param>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Is Connected,
        /// Parameter empty,
        /// Failed WMI method execution
        /// </exception>
        public void Rename(string newName, int timeoutSecondsRestart)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (string.IsNullOrEmpty(newName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "newName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("Rename"))
                {
                    inParams["newName"] = newName;
                    clust.Instance.InvokeMethod("Rename", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Rename", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.Rename", ex.Message), ex);
            }
        }

        ///<summary>
        /// Designates the quorum resource for the cluster. (Only Windows 2003)
        ///</summary>
        ///<param name="instanceMsClusterResource">ManagerObject Cluster Instance</param>
        /// <remarks>
        /// This method is available for use in the operating systems specified in the Requirements section. 
        /// Support for this method was removed in Windows Server 2008
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008,
        /// Not Connected,
        /// Failed WMI method execution
        /// </exception>
        public void SetQuorumResource(ResourceProperty instanceMsClusterResource)
        {
            SetQuorumResource(instanceMsClusterResource.Instance);
        }

        ///<summary>
        /// Designates the quorum resource for the cluster. (Only Windows 2003)
        ///</summary>
        ///<param name="instanceMsClusterResource">ManagerObject Cluster Instance</param>
        /// <remarks>
        /// This method is available for use in the operating systems specified in the Requirements section. 
        /// Support for this method was removed in Windows Server 2008
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008,
        /// Not Connected,
        /// Failed WMI method execution
        /// </exception>
        public void SetQuorumResource(ManagementBaseObject instanceMsClusterResource)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "SetQuorumResource"));
            }
            if (instanceMsClusterResource.ClassPath.Path.IndexOf("\\root\\MSCluster:MSCluster_Resource") == -1)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamInvalidObject, "\\root\\MSCluster:MSCluster_Resource", instanceMsClusterResource.ClassPath.Path));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("SetQuorumResource"))
                {
                    inParams["Resource"] = instanceMsClusterResource;
                    clust.Instance.InvokeMethod("SetQuorumResource", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetQuorumResource", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetQuorumResource", ex.Message), ex);
            }
        }

        ///<summary>
        /// Sets the quorom to a majority quorum and uses the passed-in resource as the quorum witness resource.
        ///</summary>
        ///<param name="resourceName">Resource name</param>
        ///<param name="quorumPath">The optional path that will be used to maintain quorum files.</param>
        ///<remarks>
        /// WINDOWS 2003: Designates the quorum resource for the cluster.
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void SetMajorityQuorum(string resourceName, string quorumPath)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "SetMajorityQuorum"));
            }
            if (string.IsNullOrEmpty(resourceName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "resourceName"));
            }
            if (string.IsNullOrEmpty(quorumPath))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "quorumPath"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("SetMajorityQuorum"))
                {
                    inParams["Resource"] = resourceName;
                    inParams["QuorumPath"] = quorumPath;
                    clust.Instance.InvokeMethod("SetMajorityQuorum", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetMajorityQuorum", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetMajorityQuorum", ex.Message), ex);
            }
        }

        ///<summary>
        /// Sets the quorum behavior to not be a majority and to use the passed-in disk as the quorum resource.
        ///</summary>
        ///<param name="resourceName">Resource name</param>
        ///<param name="quorumPath">The optional path that will be used to maintain quorum files.</param>
        ///<remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void SetDiskQuorum(string resourceName, string quorumPath)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "SetDiskQuorum"));
            }
            if (string.IsNullOrEmpty(resourceName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "resourceName"));
            }
            if (string.IsNullOrEmpty(quorumPath))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "quorumPath"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("SetDiskQuorum"))
                {
                    inParams["Resource"] = resourceName;
                    inParams["QuorumPath"] = quorumPath;
                    clust.Instance.InvokeMethod("SetDiskQuorum", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetDiskQuorum", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetDiskQuorum", ex.Message), ex);
            }
        }

        ///<summary>
        /// Sets the cluster to not have a node majority quorum.
        ///</summary>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008,
        /// Not Connected,
        /// Failed WMI method execution
        /// </exception>
        public void SetNodeMajorityQuorum()
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "SetNodeMajorityQuorum"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("SetNodeMajorityQuorum"))
                {
                    clust.Instance.InvokeMethod("SetNodeMajorityQuorum", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetNodeMajorityQuorum", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.SetNodeMajorityQuorum", ex.Message), ex);
            }
        }

        ///<summary>
        /// Adds a node to a cluster.
        ///</summary>
        ///<param name="nodeName">Node name</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void AddNode(string nodeName)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (string.IsNullOrEmpty(nodeName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "nodeName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("AddNode"))
                {
                    inParams["NodeName"] = nodeName;
                    clust.Instance.InvokeMethod("AddNode", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                        Refresh(RefreshOption.Nodes,nodeName);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.AddNode", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.AddNode", ex.Message), ex);
            }
        }

        ///<summary>
        /// Removes a specified node from the cluster.
        ///</summary>
        ///<param name="nodeName">Node name</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void EvictNode(string nodeName)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "EvictNode"));
            }
            if (string.IsNullOrEmpty(nodeName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "nodeName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("EvictNode"))
                {
                    inParams["NodeName"] = nodeName;
                    clust.Instance.InvokeMethod("EvictNode", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                        NodeInstances.Remove(nodeName);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.EvictNode", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.EvictNode", ex.Message), ex);
            }
        }

        ///<summary>
        /// Removes the cluster.
        ///</summary>
        ///<param name="cleanupAd">Clean up the remaining computer objects and virtual computer objects in the current directory.</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Failed WMI method execution
        /// </exception>
        /// 
        public void DestroyCluster(bool cleanupAd)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "DestroyCluster"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("DestroyCluster"))
                {
                    inParams["CleanupAD"] = cleanupAd;
                    clust.Instance.InvokeMethod("DestroyCluster", inParams, null);
                    Disconnect();
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.DestroyCluster", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.DestroyCluster", ex.Message), ex);
            }
        }

        /// <summary>
        /// Forces a node to be cleaned up.
        /// </summary>
        /// <param name="nodeName">Node name</param>
        /// <param name="timeout">The number of milliseconds that this method will wait for cleanup to complete.</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void ForceCleanup(string nodeName, UInt32 timeout)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem == WindowsOperationSystem.Windows2003 || OperationSystem == WindowsOperationSystem.Windows2003R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "ForceCleanup"));
            }
            if (string.IsNullOrEmpty(nodeName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "nodeName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("ForceCleanup"))
                {
                    inParams["NodeName"] = nodeName;
                    inParams["Timeout"] = timeout;
                    clust.Instance.InvokeMethod("ForceCleanup", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                        Refresh(RefreshOption.Nodes);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.ForceCleanup", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.ForceCleanup", ex.Message), ex);
            }
        }

        ///<summary>
        /// Adds storage to Cluster Shared Volumes.
        ///</summary>
        ///<param name="resourceName">The name of the physical disk resource to add to Cluster Shared Volumes.</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008R2.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System before Windows Server 2008R2
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void AddResourceToClusterSharedVolumes(string resourceName)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem != WindowsOperationSystem.Windows2008R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "AddResourceToClusterSharedVolumes"));
            }
            if (string.IsNullOrEmpty(resourceName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "resourceName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("AddResourceToClusterSharedVolumes"))
                {
                    inParams["Resource"] = resourceName;
                    clust.Instance.InvokeMethod("AddResourceToClusterSharedVolumes", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.AddResourceToClusterSharedVolumes", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.AddResourceToClusterSharedVolumes", ex.Message), ex);
            }
        }

        ///<summary>
        /// Remove storage to Cluster Shared Volumes.
        ///</summary>
        ///<param name="resourceName">The name of the physical disk resource to add to Cluster Shared Volumes.</param>
        /// <remarks>
        /// This method is not supported before Windows Server 2008R2.
        /// </remarks>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Operation System  before Windows Server 2008R2
        /// Not Connected,
        /// Parameters empty,
        /// Failed WMI method execution
        /// </exception>
        public void RemoveResourceToClusterSharedVolumes(string resourceName)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }
            if (OperationSystem != WindowsOperationSystem.Windows2008R2)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_SystemNotSuportMethod, OperationSystem, "RemoveResourceToClusterSharedVolumes"));
            }
            if (string.IsNullOrEmpty(resourceName))
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_ParamEmpty, "resourceName"));
            }
            try
            {
                var clust = CacheInstances ? ClusterInfo : new ClusterWmiHelpper().GetCluster(ScopeManager);
                using (var inParams = clust.Instance.GetMethodParameters("RemoveResourceFromClusterSharedVolumes"))
                {
                    inParams["Resource"] = resourceName;
                    clust.Instance.InvokeMethod("RemoveResourceFromClusterSharedVolumes", inParams, null);
                    if (CacheInstances)
                    {
                        ClusterInfo = new ClusterWmiHelpper().GetCluster(ScopeManager);
                    }
                }
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.RemoveResourceFromClusterSharedVolumes", ex.Message), ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(string.Format(Properties.Resources.Error_MethodExecute, "Cluster.RemoveResourceFromClusterSharedVolumes", ex.Message), ex);
            }
        }

        #endregion public properties

    }
}
